
package com.scalar.chiptrack.events;

import java.util.Iterator;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.File;

import org.apache.commons.digester.Digester;

import com.scalar.chiptrack.utils.ConfigManager;
import com.scalar.chiptrack.utils.FileUtils;

//Balaram, Jun 23 2005
public class SSEventListenerDefinitionParser
{

    // From config file
    private static final String EVENT_LISTENER_DEFINITION_FILE = FileUtils.fileToURL( new File( ConfigManager.getScalarEventListenersDefFile() ) ).toString();


    // Patterns to look for in Services definition file
    public static final String PATTERN_LISTENER_TAG            = "listeners/listener";
    public static final String PATTERN_EVENT_SET_TAG           = "listeners/eventset";
    public static final String PATTERN_EVENT_SET_EVENT_TAG     = "listeners/eventset/event";
	public static final String PATTERN_LISTEN_FOR_EVENT_TAG    = "listeners/listener/listenfor/event";
	public static final String PATTERN_LISTEN_FOR_EVENTSET_TAG = "listeners/listener/listenfor/eventset";


    // One and only object to used by this singleton
    private static SSEventListenerDefinitionParser listenerDefinitionParser = null;

    // Member variable to save the parsed info
    private SSEventListenerMap mListenerMap = null;
    private HashMap mDefinedEventSetMap = null;
    private ArrayList mDefinedEventList = null;
    private ArrayList mListeningEventList = null;

    // Static initialization part
    static
    {
        init();
    }

    private SSEventListenerDefinitionParser()
    {
        mListenerMap = new SSEventListenerMap();
        mDefinedEventSetMap = new HashMap();
        mDefinedEventList = new ArrayList();
        mListeningEventList = new ArrayList();
    }

    public static void init()
    {
        try
        {
            listenerDefinitionParser = new SSEventListenerDefinitionParser();

            Digester digester = new Digester();
            digester.push( listenerDefinitionParser );

			digester.addCallMethod( PATTERN_LISTENER_TAG, "registerListener", 1 );
			digester.addCallParam( PATTERN_LISTENER_TAG, 0, "className" );

			digester.addCallMethod( PATTERN_EVENT_SET_TAG, "addToDefinedEventSet", 1 );
			digester.addCallParam( PATTERN_EVENT_SET_TAG, 0, "type" );

			digester.addCallMethod( PATTERN_EVENT_SET_EVENT_TAG, "addToDefinedEventList", 1 );
			digester.addCallParam( PATTERN_EVENT_SET_EVENT_TAG, 0, "name" );

			digester.addCallMethod( PATTERN_LISTEN_FOR_EVENT_TAG, "addToListningEventList", 1 );
			digester.addCallParam( PATTERN_LISTEN_FOR_EVENT_TAG, 0, "name" );

			digester.addCallMethod( PATTERN_LISTEN_FOR_EVENTSET_TAG, "addToListeningEventSet", 1 );
			digester.addCallParam( PATTERN_LISTEN_FOR_EVENTSET_TAG, 0, "type" );

            System.out.println( "Event Listener Definition file is : " + EVENT_LISTENER_DEFINITION_FILE );
            digester.parse( EVENT_LISTENER_DEFINITION_FILE );
        }
        catch( Throwable t )
        {
            System.out.println( "Exception while parsing listener information " );
            t.printStackTrace();
        }
    }



    public static void main( String[] args ) throws Exception
    {
        SSEventListenerMap listenerMap = SSEventListenerDefinitionParser.loadEventListenersFromConfigFile();

		System.out.println( "\n\n-------------------------------------------------------------------------\n\n" );
        System.out.println( "\nService Definition file: " + EVENT_LISTENER_DEFINITION_FILE +
                            "\nNumber of Services: " + listenerMap.size() +
                            "\nList Contents: " + listenerMap );

    }



    //
    // Static methods called by other classes to get listener list information
    //
    public static SSEventListenerMap loadEventListenersFromConfigFile()
    {
        return listenerDefinitionParser.listenerMap();
    }

    public static SSEventListenerList getListenerByEventType( String eventType )
    {
        return listenerDefinitionParser.listenerByEventType( eventType );
    }


    //
    // Internal Instance methods implements
    //
    public SSEventListenerMap listenerMap()
    {
        return mListenerMap;
    }

    public SSEventListenerList listenerByEventType( String eventType )
    {
        return mListenerMap.get1( eventType );
    }



    ////////////////////////////////////////////////////////////////////////////////
    //
    //                      DIGESTER CALL BACK METHODS
    //
    ////////////////////////////////////////////////////////////////////////////////

	public void registerListener( String className ) throws Exception
	{
        Class listenerClass = Class.forName( className );
        SSEventListener eventListener = ( SSEventListener ) listenerClass.newInstance();

		String eventName = null;
		Iterator listeningEventListIterator =  mListeningEventList.iterator();
		while( listeningEventListIterator.hasNext() )
		{
			eventName = ( String ) listeningEventListIterator.next();
			SSEventListenerList list = mListenerMap.get1( eventName );
			if( list == null )
			{
				list = new SSEventListenerList();
			}

			if( list.contains( eventListener ) == false )
			{
				list.add( eventListener );	// Only one object per list, per event 
			}
			else
			{
				eventListener = null;		// Give it to GC
			}

	        mListenerMap.put( eventName, list );
		}

		mListeningEventList = new ArrayList();
		//System.out.println( "classname = " + className );
	}

	public void addToDefinedEventSet( String type ) throws Exception
	{
		mDefinedEventSetMap.put( type, mDefinedEventList );
		mDefinedEventList = new ArrayList();

		//System.out.println( "event set type = " + type );
	}

	public void addToDefinedEventList( String name ) throws Exception
	{
		mDefinedEventList.add( name );
		//System.out.println( "event name (in event set) = " + name );
	}

	public void addToListningEventList( String name ) throws Exception
	{
		mListeningEventList.add( name );
		//System.out.println( "event name (in listenfor) = " + name );
	}

	public void addToListeningEventSet( String type ) throws Exception
	{
		Iterator definedEventListIterator = ( ( ArrayList ) mDefinedEventSetMap.get( type ) ).iterator();
		while( definedEventListIterator.hasNext() )
		{
			mListeningEventList.add( definedEventListIterator.next() );
		}

		//System.out.println( "event set name (in listenfor) = " + type );
	}



}

